/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "i2c.h"
#include "usart.h"
#include "tim.h"
#include "usb.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define MAX_CMD_LEN 100

// 模式定义
#define MODE_ON      "on"
#define MODE_OFF     "off"
#define MODE_BLINK   "blink"
#define MODE_BREATH  "breath"

// 定义结构体来存储命令参数
typedef struct {
    char mode[10];
    int count;
    int interval;
} led_cmd_t;

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
int CMD = 0;
uint8_t rx_buffer[256];
uint16_t rx_index = 0;
uint16_t data_received = 0;
uint8_t rx_buffer_temp[256];
uint16_t toggle_count = 0;
uint16_t toggle_time = 0;

int delay_time = 1000;
int run_counts = 0;


void print_log(char * data);
void receive_data(void);
void show_start(void);
void led_on(void);
void led_off(void);
void led_toggle(void);
void led_toggle_task(void);
void Breathing_Light_task(void);
void Breathing_Light(void);
void PWM_Start(void);
int parse_cmd(char *cmd, led_cmd_t *led_cmd);
void process_cmd(led_cmd_t *led_cmd);
void execute_led_control(led_cmd_t *led_cmd);
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C1_Init();
  MX_LPUART1_UART_Init();
  MX_USB_PCD_Init();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */
	PWM_Start();
	show_start();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		receive_data();
		switch(CMD)
		{
			case 1://led��
				led_on();
				CMD = 0;
				break;
			case 2://led��
				led_off();
				CMD = 0;
				break;
			case 3://led��˸
				led_toggle_task();
				break;
			case 4://������
				Breathing_Light_task();
				break;
			case 5://LED���ղ�����
				break;
			default:
				break;
		}
		HAL_Delay(10);
		
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV3;
  RCC_OscInitStruct.PLL.PLLN = 20;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */
void led_on(void)
{
	__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, 181817);
}

void led_off(void)
{
	__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, 0);
}

void led_toggle(void)
{
	static uint8_t ledstatus = 0;
	if(ledstatus == 0)
	{
		led_on();
		ledstatus = 1;
	}
	else
	{
		led_off();
		ledstatus = 0;
	}
}
void PWM_Start(void)
{
    // 启动PWM 输出
    if (HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1) != HAL_OK)
    {
        Error_Handler();  // 错误处理
    }
}

void beep_on(void)
{
		__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 90908);
		if (HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3) != HAL_OK)
    {
        Error_Handler();  // 错误处理
    }
}

void beep_off(void)
{
		__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 0);
		if (HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_3) != HAL_OK)
    {
        Error_Handler();  // 错误处理
    }
}


void Breathing_Light(void)
{
    static int pwm_duty = 0;  // 初始占空比
    static int pwm_direction = 100;  // 占空比变化方向 (1表示增大，-1表示减小)

    // 更新占空比
    pwm_duty += pwm_direction;

    // 如果占空比达到最大值或最小值，改变方向
    if (pwm_duty >= 181817)
    {
				pwm_duty = 181817;
				pwm_direction = -100;  // 反向减小
				
    }
    else if (pwm_duty <= 0)
    {
				pwm_duty = 0;
        pwm_direction = 100;  // 反向增大
    }

    // 设置 PWM 占空比
    __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, pwm_duty);
}

void Breathing_Light_task(void)
{
	    char str[20]={0};  // 确保字符数组足够大
    static int pwm_duty = 0;  // 初始占空比
    static int pwm_direction = 100;  // 占空比变化方向 (1表示增大，-1表示减小)
    // 更新占空比
    pwm_duty += pwm_direction;

    // 如果占空比达到最大值或最小值，改变方向
    if (pwm_duty >= 181817)
    {
				pwm_duty = 181817;
				pwm_direction = -100;  // 反向减小
    }
    else if (pwm_duty <= 0)
    {
				pwm_duty = 0;
        pwm_direction = 100;  // 反向增大
    }
    // 设置 PWM 占空比
    __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, pwm_duty);
		if(pwm_duty == 0)
		{
			toggle_count ++;
			if((run_counts > 0) && ((toggle_count) > run_counts))
			{
					CMD = 0;
					sprintf(str, "%d", toggle_count);
					print_log("led breathe counts:");
					print_log(str);
					print_log("\r\n");
			}
		}
}

void led_toggle_task(void)
{
    char str[20]={0};  // 确保字符数组足够大
		if(delay_time != 0)
		{
			if(toggle_time == delay_time)//1s��һ��
			{
				led_toggle();
				toggle_count++;//��¼���˶��ٴ�
				if((run_counts > 0) && ((toggle_count/2) > run_counts))
				{
						CMD = 0;
						sprintf(str, "%d", toggle_count/2);
						print_log("led toggle counts:");
						print_log(str);
						print_log("\r\n");
				}
			}
			toggle_time++;
		}
}

void show_start(void)
{
	int i = 10;//led��ת10�Σ���5��
	while(i--)
	{
			led_toggle();
			HAL_Delay(500);
	}
	
	//��������0.5s�ر�
	beep_on();
	HAL_Delay(500);
	beep_off();
	
}

//���ڷ�������
void send_data(uint8_t *data, uint16_t length)
{
    if (HAL_UART_Transmit(&hlpuart1, data, length, 1000) != HAL_OK)
    {
        Error_Handler();
    }
}

void print_log(char * data)
{
	send_data((uint8_t *)data,strlen(data));
}

void receive_data(void)
{
	led_cmd_t led_cmd;
	if(data_received == 1)
	{
		if(rx_index < sizeof(rx_buffer))
		{
			memcpy(rx_buffer_temp,rx_buffer,rx_index);
			
			if (strcmp(rx_buffer_temp, "ledOFF") == 0) {
					print_log("LED OFF!\r\n");
					CMD = 1;
			} else if (strcmp(rx_buffer_temp, "ledON") == 0) {
					print_log("LED ON!\r\n");
					CMD = 2;
			} else if (strcmp(rx_buffer_temp, "ledblink") == 0) {
					print_log("Blinking LED...\r\n");
					toggle_count = 0;
					toggle_time  = 50;
					delay_time = 50;
					run_counts = 10;
					CMD = 3;
			} else if (strcmp(rx_buffer_temp, "ledbreath") == 0) {
					print_log("Breathing LED...\r\n");
					toggle_count = 0;
					toggle_time  = 50;
					delay_time = 50;
					run_counts = 10;
					CMD = 4;
			} else if (strncmp(rx_buffer_temp, "ledctl", 6) == 0) {
					print_log("Ledctl command processed\r\n");
			} else if (strcmp(rx_buffer_temp, "Clear") == 0) {
					print_log("\x1B[2J\x1B[H");
			}else if (strcmp(rx_buffer_temp, "\n") == 0) {//���յ��س�\n����ӡTALOS
					print_log("TALOS");
			}else if (rx_index ==1 &&  rx_buffer_temp[0] == 0x03 ) {//���յ�Ctrl + C����ӡTALOS
					print_log("TALOS");
					CMD = 0;
			}else if (rx_index > 20) {
					if (parse_cmd(rx_buffer_temp, &led_cmd) == 0) {
        // 处理命令
							process_cmd(&led_cmd);
					} else {
							printf("Invalid command.\n");
					}

					print_log("TALOS");
					CMD = 0;
			} 			
			else {
					print_log("Input Error!!\r\n");
			}
		}
		
		data_received = 0;//ʹ�ܽ���
	}
}
// 解析命令函数
int parse_cmd(char *cmd, led_cmd_t *led_cmd) {
    char *token;
    char *delim = " \n";

    // 初始化结构体
    memset(led_cmd, 0, sizeof(led_cmd_t));

    // 解析每个参数
    token = strtok(cmd, delim);
    while (token != NULL) {
        if (strcmp(token, "--m") == 0) {
            token = strtok(NULL, delim);
            if (token != NULL) {
                strncpy(led_cmd->mode, token, sizeof(led_cmd->mode) - 1);
            } else {
                return -1; // 缺少模式
            }
        } else if (strcmp(token, "--c") == 0) {
            token = strtok(NULL, delim);
            if (token != NULL) {
                led_cmd->count = atoi(token); // 转换为整数
            } else {
                return -1; // 缺少次数
            }
        } else if (strcmp(token, "--i") == 0) {
            token = strtok(NULL, delim);
            if (token != NULL) {
                led_cmd->interval = atoi(token); // 转换为整数
            } else {
                return -1; // 缺少间隔时间
            }
        }
        token = strtok(NULL, delim);
    }

    // 检查必要的模式参数
    if (strlen(led_cmd->mode) == 0) {
        return -1; // 缺少模式
    }

    return 0;
}
// 处理命令
void process_cmd(led_cmd_t *led_cmd) {
    printf("Mode: %s\n", led_cmd->mode);
    printf("Count: %d\n", led_cmd->count);
    printf("Interval: %d ms\n", led_cmd->interval);

    // 执行 LED 控制
    execute_led_control(led_cmd);
}
// 执行 LED 控制
void execute_led_control(led_cmd_t *led_cmd) {
    // 根据模式执行不同操作
    if (strcmp(led_cmd->mode, MODE_ON) == 0) {
					print_log("LED ON!\r\n");
					CMD = 2;
    } else if (strcmp(led_cmd->mode, MODE_OFF) == 0) {
					print_log("LED OFF!\r\n");
					CMD = 1;
    } else if (strcmp(led_cmd->mode, MODE_BLINK) == 0) {
					print_log("Blinking LED...\r\n");
					toggle_count = 0;
					toggle_time  = led_cmd->interval;
					delay_time = led_cmd->interval;
					run_counts = led_cmd->count;
					CMD = 3;
    } else if (strcmp(led_cmd->mode, MODE_BREATH) == 0) {
					print_log("Breathing LED...\r\n");
					toggle_count = 0;
					toggle_time  = led_cmd->interval;
					delay_time = led_cmd->interval;
					run_counts = led_cmd->count;
					CMD = 4;
    } else {
        printf("Invalid mode.\n");
    }
}

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
